#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 设置棋盘大小
    setFixedSize(MARGIN * 2 + BLOCK_SIZE * KBOARD_SIZE_NUM, MARGIN * 2 + BLOCK_SIZE * KBOARD_SIZE_NUM);
    //setStyleSheet("background-color:blue;");

    // 开启鼠标监控功能，这两句一般要设置window的
    setMouseTracking(true);
    //centralWidget()->setMouseTracking(true);

    initGame();
}

MainWindow::~MainWindow()
{
    if (game)
    {
        delete game;
        game = nullptr;
    }
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    //设置画笔
    QPainter painter(this);
    // 绘制棋盘
    painter.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿

    for (int i = 0; i <= KBOARD_SIZE_NUM; i++)
    {
        //画线
        painter.drawLine(QPoint(MARGIN + BLOCK_SIZE * i, MARGIN),
                         QPoint(MARGIN + BLOCK_SIZE * i, size().height() - MARGIN));
        painter.drawLine(QPoint(size().height() - MARGIN, MARGIN + BLOCK_SIZE * i),
                         QPoint(MARGIN, MARGIN + BLOCK_SIZE * i));
    }

    //设置笔刷
    QBrush brush;
    brush.setStyle(Qt::SolidPattern);
    // 绘制落子标记(防止鼠标出框越界)
    if (clickPosRow > 0 && clickPosRow < KBOARD_SIZE_NUM &&
        clickPosCol > 0 && clickPosCol < KBOARD_SIZE_NUM &&
        game->gameMapVec[clickPosRow][clickPosCol] == 0)
    {
        if (game->playerFlag)
            brush.setColor(Qt::black);  //设置颜色
        else
            brush.setColor(Qt::white);
        painter.setBrush(brush);
        //画圆
        painter.drawEllipse(MARGIN + BLOCK_SIZE * clickPosCol - MARK_SIZE / 2, MARGIN + BLOCK_SIZE * clickPosRow - MARK_SIZE / 2, MARK_SIZE, MARK_SIZE);
    }

    // 绘制棋子
    for (int i = 0; i < KBOARD_SIZE_NUM; i++)
        for (int j = 0; j < KBOARD_SIZE_NUM; j++)
        {
            if (game->gameMapVec[i][j] == 1)
            {
                brush.setColor(Qt::black);
                painter.setBrush(brush);
                painter.drawEllipse(MARGIN + BLOCK_SIZE * j - CHESS_RADIUS, MARGIN + BLOCK_SIZE * i - CHESS_RADIUS, CHESS_RADIUS * 2, CHESS_RADIUS * 2);
            }
            else if (game->gameMapVec[i][j] == -1)
            {
                brush.setColor(Qt::white);
                painter.setBrush(brush);
                painter.drawEllipse(MARGIN + BLOCK_SIZE * j - CHESS_RADIUS, MARGIN + BLOCK_SIZE * i - CHESS_RADIUS, CHESS_RADIUS * 2, CHESS_RADIUS * 2);
            }
        }

    // 判断输赢
    if (clickPosRow > 0 && clickPosRow < KBOARD_SIZE_NUM &&
        clickPosCol > 0 && clickPosCol < KBOARD_SIZE_NUM &&
        (game->gameMapVec[clickPosRow][clickPosCol] == 1 ||
            game->gameMapVec[clickPosRow][clickPosCol] == -1))
    {
        if (game->isWin(clickPosRow, clickPosCol) && game->gameStatus == PLAYING)
        {
            qDebug() << "win";
            game->gameStatus = WIN;
            QString str;
            if (game->gameMapVec[clickPosRow][clickPosCol] == 1)
                str = "white player";
            else if (game->gameMapVec[clickPosRow][clickPosCol] == -1)
                str = "black player";
            QMessageBox::StandardButton btnValue = QMessageBox::information(this, "congratulations", str + " win!");

            // 重置游戏状态，否则容易死循环
            if (btnValue == QMessageBox::Ok)
            {
                game->startGame(game_type);
                game->gameStatus = PLAYING;
            }
        }
    }


    // 判断死局
    if (game->isDeadGame())
    {
        QMessageBox::StandardButton btnValue = QMessageBox::information(this, "oops", "dead game!");
        if (btnValue == QMessageBox::Ok)
        {
            game->startGame(game_type);
            game->gameStatus = PLAYING;
        }

    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    // 通过鼠标的hover确定落子的标记
    int x = event->x();
    int y = event->y();

    // 棋盘边缘不能落子
    if (x >= MARGIN + BLOCK_SIZE / 2 &&
            x < size().width() - MARGIN &&
            y >= MARGIN + BLOCK_SIZE / 2 &&
            y < size().height()- MARGIN)
    {
        // 获取最近的左上角的点
        int col = x / BLOCK_SIZE;
        int row = y / BLOCK_SIZE;

        int leftTopPosX = MARGIN + BLOCK_SIZE * col;
        int leftTopPosY = MARGIN + BLOCK_SIZE * row;

        // 根据距离算出合适的点击位置,一共四个点，根据半径距离选最近的
        clickPosRow = -1; // 初始化最终的值
        clickPosCol = -1;
        int len = 0; // 计算完后取整就可以了

        // 确定一个误差在范围内的点，且只可能确定一个出来
        len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < FUZZY_DISTANCE)
        {
            clickPosRow = row;
            clickPosCol = col;
        }
        len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < FUZZY_DISTANCE)
        {
            clickPosRow = row;
            clickPosCol = col + 1;
        }
        len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
        if (len < FUZZY_DISTANCE)
        {
            clickPosRow = row + 1;
            clickPosCol = col;
        }
        len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE) + (y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
        if (len < FUZZY_DISTANCE)
        {
            clickPosRow = row + 1;
            clickPosCol = col + 1;
        }
    }

    // 存了坐标后也要重绘
    update();
}

void MainWindow::initGame()
{
    // 初始化游戏模型
    game = new GameModel;
    initPVEGame();
}

void MainWindow::initPVEGame()
{
    game_type = AI;
    game->gameStatus = PLAYING;
    game->startGame(game_type);
    update();
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    // 人下棋，并且不能抢机器的棋
    if (!(game_type == AI && !game->playerFlag))
    {
        chessOneByPerson();
        // 如果是人机模式，需要调用AI下棋
        if (game->gameType == AI && !game->playerFlag)
        {
            // 用定时器做一个延迟
            QTimer::singleShot(AI_DELAY, this, SLOT(chessOneByAI()));
        }
    }

}

void MainWindow::chessOneByPerson()
{
    // 根据当前存储的坐标下子
    // 只有有效点击才下子，并且该处没有子
    if (clickPosRow != -1 && clickPosCol != -1 && game->gameMapVec[clickPosRow][clickPosCol] == 0)
    {
        game->actionByPerson(clickPosRow, clickPosCol);

        // 重绘
        update();
    }
}

void MainWindow::chessOneByAI()
{
    game->actionByAI(clickPosRow, clickPosCol);
    update();
}
